<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: How OpenCV-Python Bindings Works?</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d6/d00/tutorial_py_root.html">OpenCV-Python Tutorials</a></li><li class="navelem"><a class="el" href="../../df/da2/tutorial_py_table_of_contents_bindings.html">OpenCV-Python Bindings</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">How OpenCV-Python Bindings Works? </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<p>Learn:</p>
<ul>
<li>How OpenCV-Python bindings are generated?</li>
<li>How to extend new OpenCV modules to Python?</li>
</ul>
<h2>How OpenCV-Python bindings are generated? </h2>
<p>In OpenCV, all algorithms are implemented in C++. But these algorithms can be used from different languages like Python, Java etc. This is made possible by the bindings generators. These generators create a bridge between C++ and Python which enables users to call C++ functions from Python. To get a complete picture of what is happening in background, a good knowledge of Python/C API is required. A simple example on extending C++ functions to Python can be found in official Python documentation[1]. So extending all functions in OpenCV to Python by writing their wrapper functions manually is a time-consuming task. So OpenCV does it in a more intelligent way. OpenCV generates these wrapper functions automatically from the C++ headers using some Python scripts which are located in <code>modules/python/src2</code>. We will look into what they do.</p>
<p>First, <code>modules/python/CMakeFiles.txt</code> is a CMake script which checks the modules to be extended to Python. It will automatically check all the modules to be extended and grab their header files. These header files contain list of all classes, functions, constants etc. for that particular modules.</p>
<p>Second, these header files are passed to a Python script, <code>modules/python/src2/gen2.py</code>. This is the Python bindings generator script. It calls another Python script <code>modules/python/src2/hdr_parser.py</code>. This is the header parser script. This header parser splits the complete header file into small Python lists. So these lists contain all details about a particular function, class etc. For example, a function will be parsed to get a list containing function name, return type, input arguments, argument types etc. Final list contains details of all the functions, enums, structs, classes etc. in that header file.</p>
<p>But header parser doesn't parse all the functions/classes in the header file. The developer has to specify which functions should be exported to Python. For that, there are certain macros added to the beginning of these declarations which enables the header parser to identify functions to be parsed. These macros are added by the developer who programs the particular function. In short, the developer decides which functions should be extended to Python and which are not. Details of those macros will be given in next session.</p>
<p>So header parser returns a final big list of parsed functions. Our generator script (gen2.py) will create wrapper functions for all the functions/classes/enums/structs parsed by header parser (You can find these header files during compilation in the <code>build/modules/python/</code> folder as pyopencv_generated_*.h files). But there may be some basic OpenCV datatypes like Mat, Vec4i, Size. They need to be extended manually. For example, a Mat type should be extended to Numpy array, Size should be extended to a tuple of two integers etc. Similarly, there may be some complex structs/classes/functions etc. which need to be extended manually. All such manual wrapper functions are placed in <code>modules/python/src2/cv2.cpp</code>.</p>
<p>So now only thing left is the compilation of these wrapper files which gives us <b>cv2</b> module. So when you call a function, say <code>res = equalizeHist(img1,img2)</code> in Python, you pass two numpy arrays and you expect another numpy array as the output. So these numpy arrays are converted to <a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a> and then calls the <a class="el" href="../../d6/dc7/group__imgproc__hist.html#ga7e54091f0c937d49bf84152a16f76d6e" title="Equalizes the histogram of a grayscale image. ">equalizeHist()</a> function in C++. Final result, res will be converted back into a Numpy array. So in short, almost all operations are done in C++ which gives us almost same speed as that of C++.</p>
<p>So this is the basic version of how OpenCV-Python bindings are generated.</p>
<h2>How to extend new modules to Python? </h2>
<p>Header parser parse the header files based on some wrapper macros added to function declaration. Enumeration constants don't need any wrapper macros. They are automatically wrapped. But remaining functions, classes etc. need wrapper macros.</p>
<p>Functions are extended using <code>CV_EXPORTS_W</code> macro. An example is shown below. </p><div class="fragment"><div class="line"><a class="code" href="../../db/de0/group__core__utils.html#ga67ea671a3582ce612ac3c281e067f480">CV_EXPORTS_W</a> <span class="keywordtype">void</span> <a class="code" href="../../d6/dc7/group__imgproc__hist.html#ga7e54091f0c937d49bf84152a16f76d6e">equalizeHist</a>( <a class="code" href="../../dc/d84/group__core__basic.html#ga353a9de602fe76c709e12074a6f362ba">InputArray</a> src, <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> dst );</div></div><!-- fragment --><p> Header parser can understand the input and output arguments from keywords like InputArray, OutputArray etc. But sometimes, we may need to hardcode inputs and outputs. For that, macros like <code>CV_OUT</code>, <code>CV_IN_OUT</code> etc. are used. </p><div class="fragment"><div class="line"><a class="code" href="../../db/de0/group__core__utils.html#ga67ea671a3582ce612ac3c281e067f480">CV_EXPORTS_W</a> <span class="keywordtype">void</span> <a class="code" href="../../d3/dc0/group__imgproc__shape.html#ga8ce13c24081bbc7151e9326f412190f1">minEnclosingCircle</a>( <a class="code" href="../../dc/d84/group__core__basic.html#ga353a9de602fe76c709e12074a6f362ba">InputArray</a> points,</div><div class="line">                                     <a class="code" href="../../db/de0/group__core__utils.html#ga4e999bc21cb894d3ed789f3f0bc26778">CV_OUT</a> <a class="code" href="../../dc/d84/group__core__basic.html#ga7d080aa40de011e4410bca63385ffe2a">Point2f</a>&amp; center, <a class="code" href="../../db/de0/group__core__utils.html#ga4e999bc21cb894d3ed789f3f0bc26778">CV_OUT</a> <span class="keywordtype">float</span>&amp; radius );</div></div><!-- fragment --><p> For large classes also, <code>CV_EXPORTS_W</code> is used. To extend class methods, <code>CV_WRAP</code> is used. Similarly, <code>CV_PROP</code> is used for class fields. </p><div class="fragment"><div class="line"><span class="keyword">class </span><a class="code" href="../../db/de0/group__core__utils.html#ga67ea671a3582ce612ac3c281e067f480">CV_EXPORTS_W</a> CLAHE : <span class="keyword">public</span> Algorithm</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#gae435babf3ce7cca990524b23adf6b4a3">CV_WRAP</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> apply(<a class="code" href="../../dc/d84/group__core__basic.html#ga353a9de602fe76c709e12074a6f362ba">InputArray</a> src, <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> dst) = 0;</div><div class="line"></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#gae435babf3ce7cca990524b23adf6b4a3">CV_WRAP</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> setClipLimit(<span class="keywordtype">double</span> clipLimit) = 0;</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#gae435babf3ce7cca990524b23adf6b4a3">CV_WRAP</a> <span class="keyword">virtual</span> <span class="keywordtype">double</span> getClipLimit() <span class="keyword">const</span> = 0;</div><div class="line">}</div></div><!-- fragment --><p> Overloaded functions can be extended using <code>CV_EXPORTS_AS</code>. But we need to pass a new name so that each function will be called by that name in Python. Take the case of integral function below. Three functions are available, so each one is named with a suffix in Python. Similarly <code>CV_WRAP_AS</code> can be used to wrap overloaded methods. </p><div class="fragment"><div class="line"><a class="code" href="../../db/de0/group__core__utils.html#ga67ea671a3582ce612ac3c281e067f480">CV_EXPORTS_W</a> <span class="keywordtype">void</span> <a class="code" href="../../d5/df1/group__imgproc__hal__functions.html#ga78d53bcbe1710d0f7034e89fd0d43259">integral</a>( <a class="code" href="../../dc/d84/group__core__basic.html#ga353a9de602fe76c709e12074a6f362ba">InputArray</a> src, <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> sum, <span class="keywordtype">int</span> sdepth = -1 );</div><div class="line"></div><div class="line"><a class="code" href="../../db/de0/group__core__utils.html#ga288d5d11e4d8675aab962ec2b2066855">CV_EXPORTS_AS</a>(integral2) <span class="keywordtype">void</span> <a class="code" href="../../d5/df1/group__imgproc__hal__functions.html#ga78d53bcbe1710d0f7034e89fd0d43259">integral</a>( <a class="code" href="../../dc/d84/group__core__basic.html#ga353a9de602fe76c709e12074a6f362ba">InputArray</a> src, <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> sum,</div><div class="line">                                        <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> sqsum, <span class="keywordtype">int</span> sdepth = -1, <span class="keywordtype">int</span> sqdepth = -1 );</div><div class="line"></div><div class="line"><a class="code" href="../../db/de0/group__core__utils.html#ga288d5d11e4d8675aab962ec2b2066855">CV_EXPORTS_AS</a>(integral3) <span class="keywordtype">void</span> <a class="code" href="../../d5/df1/group__imgproc__hal__functions.html#ga78d53bcbe1710d0f7034e89fd0d43259">integral</a>( <a class="code" href="../../dc/d84/group__core__basic.html#ga353a9de602fe76c709e12074a6f362ba">InputArray</a> src, <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> sum,</div><div class="line">                                        <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> sqsum, <a class="code" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">OutputArray</a> tilted,</div><div class="line">                                        <span class="keywordtype">int</span> sdepth = -1, <span class="keywordtype">int</span> sqdepth = -1 );</div></div><!-- fragment --><p> Small classes/structs are extended using <code>CV_EXPORTS_W_SIMPLE</code>. These structs are passed by value to C++ functions. Examples are <code>KeyPoint</code>, <code>Match</code> etc. Their methods are extended by <code>CV_WRAP</code> and fields are extended by <code>CV_PROP_RW</code>. </p><div class="fragment"><div class="line"><span class="keyword">class </span><a class="code" href="../../db/de0/group__core__utils.html#ga13d649e3f5582a106caaa98f187dd34b">CV_EXPORTS_W_SIMPLE</a> DMatch</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#gae435babf3ce7cca990524b23adf6b4a3">CV_WRAP</a> DMatch();</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#gae435babf3ce7cca990524b23adf6b4a3">CV_WRAP</a> DMatch(<span class="keywordtype">int</span> _queryIdx, <span class="keywordtype">int</span> _trainIdx, <span class="keywordtype">float</span> _distance);</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#gae435babf3ce7cca990524b23adf6b4a3">CV_WRAP</a> DMatch(<span class="keywordtype">int</span> _queryIdx, <span class="keywordtype">int</span> _trainIdx, <span class="keywordtype">int</span> _imgIdx, <span class="keywordtype">float</span> _distance);</div><div class="line"></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga9e800d960e0fc30e7f83c67c98e69ed2">CV_PROP_RW</a> <span class="keywordtype">int</span> queryIdx; <span class="comment">// query descriptor index</span></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga9e800d960e0fc30e7f83c67c98e69ed2">CV_PROP_RW</a> <span class="keywordtype">int</span> trainIdx; <span class="comment">// train descriptor index</span></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga9e800d960e0fc30e7f83c67c98e69ed2">CV_PROP_RW</a> <span class="keywordtype">int</span> imgIdx;   <span class="comment">// train image index</span></div><div class="line"></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga9e800d960e0fc30e7f83c67c98e69ed2">CV_PROP_RW</a> <span class="keywordtype">float</span> distance;</div><div class="line">};</div></div><!-- fragment --><p> Some other small classes/structs can be exported using <code>CV_EXPORTS_W_MAP</code> where it is exported to a Python native dictionary. <code>Moments()</code> is an example of it. </p><div class="fragment"><div class="line"><span class="keyword">class </span><a class="code" href="../../db/de0/group__core__utils.html#gaff7195942cab00fc5eafdd8ed777fac5">CV_EXPORTS_W_MAP</a> Moments</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga9e800d960e0fc30e7f83c67c98e69ed2">CV_PROP_RW</a> <span class="keywordtype">double</span>  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga9e800d960e0fc30e7f83c67c98e69ed2">CV_PROP_RW</a> <span class="keywordtype">double</span>  mu20, mu11, mu02, mu30, mu21, mu12, mu03;</div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga9e800d960e0fc30e7f83c67c98e69ed2">CV_PROP_RW</a> <span class="keywordtype">double</span>  nu20, nu11, nu02, nu30, nu21, nu12, nu03;</div><div class="line">};</div></div><!-- fragment --><p> So these are the major extension macros available in OpenCV. Typically, a developer has to put proper macros in their appropriate positions. Rest is done by generator scripts. Sometimes, there may be an exceptional cases where generator scripts cannot create the wrappers. Such functions need to be handled manually, to do this write your own <code>pyopencv_*.hpp</code> extending headers and put them into misc/python subdirectory of your module. But most of the time, a code written according to OpenCV coding guidelines will be automatically wrapped by generator scripts.</p>
<p>More advanced cases involves providing Python with additional features that does not exist in the C++ interface such as extra methods, type mappings, or to provide default arguments. We will take <code>UMat</code> datatype as an example of such cases later on. First, to provide Python-specific methods, <code>CV_WRAP_PHANTOM</code> is utilized in a similar manner to <code>CV_WRAP</code>, except that it takes the method header as its argument, and you would need to provide the method body in your own <code>pyopencv_*.hpp</code> extension. <code>UMat::queue()</code> and <code>UMat::context()</code> are an example of such phantom methods that does not exist in C++ interface, but are needed to handle OpenCL functionalities at the Python side. Second, if an already-existing datatype(s) is mappable to your class, it is highly preferable to indicate such capacity using <code>CV_WRAP_MAPPABLE</code> with the source type as its argument, rather than crafting your own binding function(s). This is the case of <code>UMat</code> which maps from <code>Mat</code>. Finally, if a default argument is needed, but it is not provided in the native C++ interface, you can provide it for Python side as the argument of <code>CV_WRAP_DEFAULT</code>. As per the <code>UMat::getMat</code> example below: </p><div class="fragment"><div class="line"><span class="keyword">class </span><a class="code" href="../../db/de0/group__core__utils.html#ga67ea671a3582ce612ac3c281e067f480">CV_EXPORTS_W</a> UMat</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    <span class="comment">// You would need to provide `static bool cv_mappable_to(const Ptr&lt;Mat&gt;&amp; src, Ptr&lt;UMat&gt;&amp; dst)`</span></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#gacbb88034b7de34a8b35aa42f3216a94e">CV_WRAP_MAPPABLE</a>(Ptr&lt;Mat&gt;);</div><div class="line"></div><div class="line">    /! returns the OpenCL queue used by OpenCV UMat.</div><div class="line">    <span class="comment">// You would need to provide the method body in the binder code</span></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga6c6ee613d3eebd87f9f391fcde4a6cde">CV_WRAP_PHANTOM</a>(<span class="keyword">static</span> <span class="keywordtype">void</span>* queue());</div><div class="line"></div><div class="line">    <span class="comment">// You would need to provide the method body in the binder code</span></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga6c6ee613d3eebd87f9f391fcde4a6cde">CV_WRAP_PHANTOM</a>(<span class="keyword">static</span> <span class="keywordtype">void</span>* context());</div><div class="line"></div><div class="line">    <a class="code" href="../../db/de0/group__core__utils.html#ga6a1f29cf8d55c0ee1b4687f6006da0b9">CV_WRAP_AS</a>(<span class="keyword">get</span>) Mat getMat(<span class="keywordtype">int</span> flags <a class="code" href="../../db/de0/group__core__utils.html#ga92152159130797a2713a0992dd5239d2">CV_WRAP_DEFAULT</a>(<a class="code" href="../../dc/d84/group__core__basic.html#gga6226c29c7b0e7bda7aff72e96ba8e1dfaf44732c797cd59f5940e426ecd62f45f">ACCESS_RW</a>)) const;</div><div class="line">};</div></div><!-- fragment --> </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
